package com.ts.camera2.TsCamera

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.ImageFormat
import android.graphics.SurfaceTexture
import android.hardware.Camera
import android.hardware.camera2.CameraCaptureSession
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraDevice
import android.hardware.camera2.CameraManager
import android.hardware.camera2.CaptureFailure
import android.hardware.camera2.CaptureRequest
import android.media.ImageReader
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.util.Size
import android.view.Surface
import androidx.core.app.ActivityCompat
import java.util.Arrays
import kotlin.math.abs

class Camera2Util {


    private val TAG = "Camera2Util"


    private var mSession: CameraCaptureSession? = null
    fun startPreview() {

        mCameraDevice?.createCaptureSession(
            listOf<Surface>(surface!!, mImageReader?.surface!!),
            object : CameraCaptureSession.StateCallback() {
                override fun onConfigured(session: CameraCaptureSession) {
                    mSession = session
                    preview(surface!!)
                }

                override fun onConfigureFailed(session: CameraCaptureSession) {

                }
            },
            mHandler
        );
    }

    private val THRESHOLD = 0.001f
    private var mPreviewSize: Size? = null
    private var mSupportPreviewSize: ArrayList<Size>? = null
    private var mSupportPictureSize: ArrayList<Size>? = null
    private val mDefaultPreviewSize = Size(1280, 720)
    private var mSensorOrientation: Int? = null
    private var mPictureSize: Size? = null
    private val mDefaultCaptureSize = Size(1280, 720)
    fun getCameraInfo(cameradId: String, mCameraManager: CameraManager) {
        var characteristics: CameraCharacteristics? = null


        characteristics = mCameraManager.getCameraCharacteristics(cameradId)
        val streamConfigs =
            characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
        if (streamConfigs != null) {

            mSupportPreviewSize?.addAll(
                streamConfigs.getOutputSizes(
                    SurfaceTexture::class.java
                )
            )

            var supportDefaultSize = false
            var sameRatioSize: Size? = null
            var defaultRatio: Float =
                mDefaultPreviewSize.getWidth() * 1.0f / mDefaultPreviewSize.getHeight()
            mPreviewSize = mSupportPreviewSize!![mSupportPreviewSize!!.size / 2]
            mSupportPreviewSize?.forEachIndexed { index, size ->
                val ratio = size.width * 1.0f / size.height
                if (abs((ratio - defaultRatio).toDouble()) < THRESHOLD) {
                    sameRatioSize = size
                }

                if (mDefaultPreviewSize.width == size.width && mDefaultPreviewSize.height == size.height) {
                    Log.d(TAG, "initCamera2Wrapper() called supportDefaultSize ")
                    supportDefaultSize = true

                }


            }


            if (supportDefaultSize) {
                mPreviewSize = mDefaultPreviewSize
            } else if (sameRatioSize != null) {
                mPreviewSize = sameRatioSize
            }


            supportDefaultSize = false
            sameRatioSize = null
            defaultRatio = mDefaultCaptureSize.width * 1.0f / mDefaultCaptureSize.height
            mSupportPictureSize?.addAll(
                listOf<Size>(*streamConfigs.getOutputSizes(ImageFormat.YUV_420_888))
            )
            mPictureSize = mSupportPictureSize?.get(0)
            for (size in mSupportPictureSize!!) {
                Log.d(
                    TAG,
                    "initCamera2Wrapper() called mSupportPictureSize " + size.width + "x" + size.height
                )
                val ratio = size.width * 1.0f / size.height
                if (abs((ratio - defaultRatio).toDouble()) < THRESHOLD) {
                    sameRatioSize = size
                }

                if (mDefaultCaptureSize.getWidth() == size.width && mDefaultCaptureSize.getHeight() == size.height) {
                    supportDefaultSize = true
                    break
                }
            }
            if (supportDefaultSize) {
                mPictureSize = mDefaultCaptureSize
            } else if (sameRatioSize != null) {
                mPictureSize = sameRatioSize
            }
        }
        mSensorOrientation = characteristics.get<Int>(CameraCharacteristics.SENSOR_ORIENTATION)
        Log.d(TAG, "initCamera2Wrapper() called mSensorOrientation = $mSensorOrientation")

    }



    var mCaptureRequest: CaptureRequest?=null

    private fun preview(surface: Surface) {
        // 通过模板创建RequestBuilder
        // CaptureRequest还可以配置很多其他信息，例如图像格式、图像分辨率、传感器控制、闪光灯控制、
        // 3A(自动对焦-AF、自动曝光-AE和自动白平衡-AWB)控制等
        val previewRequestBuilder =
            mCameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)

        // 设置预览画面
        previewRequestBuilder.addTarget(surface)

        mCaptureRequest = previewRequestBuilder.build()
        mSession?.setRepeatingRequest(mCaptureRequest!!, object :
            CameraCaptureSession.CaptureCallback() {

            override fun onCaptureStarted(
                session: CameraCaptureSession,
                request: CaptureRequest,
                timestamp: Long,
                frameNumber: Long
            ) {
                super.onCaptureStarted(session, request, timestamp, frameNumber)
                Log.e(TAG,"onCaptureStarted")
            }


            override fun onCaptureFailed(
                session: CameraCaptureSession,
                request: CaptureRequest,
                failure: CaptureFailure
            ) {
                super.onCaptureFailed(session, request, failure)
                Log.e(TAG,"onCaptureFailed")
            }

        }, mHandler)
    }


    var mCameraDevice:CameraDevice?=null
    var callBack=object: CameraDevice.StateCallback() {
        override fun onOpened(camera: CameraDevice) {
           Log.e(TAG,"onOpened")
            mCameraDevice=camera;
            mImageReader=getImageReader()
            startPreview();

        }

        override fun onDisconnected(camera: CameraDevice) {
            Log.e(TAG,"onDisconnected")
        }

        override fun onError(camera: CameraDevice, error: Int) {
            Log.e(TAG, "onError$error")
        }
    }
    var mFacingType: Int = CameraCharacteristics.LENS_FACING_BACK
    private val mHandler = Handler(Looper.getMainLooper())
    var mCameraCharacteristics:CameraCharacteristics?=null
    var cameraId="";
    var surface:Surface?=null

   private var mLargestSize: Camera.Size? = null
     private var mImageReader: ImageReader? = null
    private fun getImageReader(): ImageReader {
                // ImageReader是获取图像数据的重要途径
        return ImageReader.newInstance(
            mLargestSize!!.width,
            mLargestSize!!.height,
            ImageFormat.JPEG,
            // Image对象池的大小，指定了能从ImageReader获取Image对象的最大值，过多获取缓冲区可能导致OOM，
            // 所以最好按照最少的需要去设置这个值
            2
        )
    }
    fun openCamera2(context:Context,surface:Surface){
        this.surface=surface
        var cameraManager=context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
        for (s in cameraManager.cameraIdList) {
            val characteristics = cameraManager.getCameraCharacteristics(s)
//            val level = characteristics.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL)
            val internal = characteristics.get(CameraCharacteristics.LENS_FACING)
            if (internal == mFacingType) {
                    cameraId = s
                    mCameraCharacteristics = characteristics
            }
            Log.e(TAG,"cameraId:$cameraId")
        }


        if (ActivityCompat.checkSelfPermission(
                context,
                Manifest.permission.CAMERA
            ) != PackageManager.PERMISSION_GRANTED
        ) {

            return
        }
        cameraManager.openCamera(cameraId,callBack,mHandler)




    }
}